2015-08-22

創用 CC 授權條款

Taiwan R User Group / MLDM Monday

Function / Program in R

Program:

程式:

資料 or 資料結構





Data Structure:


剛剛上一位講者: Ning 已經教過了,

別忘了要記得用swirl()複習喔!

什麼叫程式





目的是用來處理「特定資料」,

根據演算法將多個函式或是指令組成的集合




簡單說,寫一個程式,其實和 寫一段文章,或是一篇小說差不多,

Function 或 演算法





數學上叫函數,

程式語言中叫函式

為什麼要用function:



1. 可以把「相同目的」的"指令"和"資料"
 整理在一起


2. 可重複使用


3. "可方便閱讀程式"


by 民明書房 Noah

function的說明:

可用R來查詢定義:




?function(){}


用法:




函式名稱 = function(引數) {

    程式的內容........

}

引數:表示可以把資料從function外面引導到function裏面的橋樑,
引數不一定要給

提醒:愛護生命,建議千萬不要用中文當作變數及函式名字,現在用中文只是為了說明

function的使用方法:





    函式名稱()


再次提醒:家人朋友都很愛你,別想不開用中文當作變數及函式名字

顯示 Hello World




請在R 中顯示:Hello World, R

方法:


  "Hello World, R"

  print("Hello World, R")

  paste("Hello World, R")

選擇print()





  print("Hello World, R")

function的製作方法:




函式名稱 = function(引數) {

   程式的內容........

}

function的製作方法:




函式名稱 = function(引數) {

  print("Hello World, R")

}

再次提醒:愛護生命,千萬不要用中文當作變數及函式名字

Hello World

第一個R的程式:


helloworld <- function(){

  print("Hello World, R")

}

helloworld()

## [1] "Hello World, R"

範例:可以用引數帶入資料變數


hi <- function(your_friend_name){

  print(paste("Hi ", your_friends_name))
}

執行:

hi("Everybody")

## [1] "Hi, Everybody"

hi:函式名稱,
your_friend_name:此函式所帶入的參數,

稍微有難度的範例:




my_friends=c("Dboy", "Ning", "Noah")

hi(my_friends)
## [1] "Hi, Dboy" "Hi, Ning" "Hi, Noah"

範例2:

顯示現在的時間:


print("現在的時間和日期是:")

print(date())


## [1] "現在的時間和日期是:"
## [1] "Sat Aug 22 01:40:51 2015"





> date() 
[1] "Thu Aug 20 03:50:13 2015"

分別顯示現在的日期和時間:substr


    print("現在的日期是:")

    print(paste(substr(date(),21,24), 
        substr(date(),5,10), substr(date(),1,3)))

## [1] "現在的日期是:"
## [1] "2015 Aug 22 Sat"

    print("現在的時間是:")

    print(substr(date(),12,19))

## [1] "現在的時間是:"
## [1] "01:40:51"

分別顯示現在的日期和時間:strsplit


  now_time = unlist(strsplit(date(), " "))[4]
  print("現在的時間是:")
  print(now_time)


  n1 = unlist(strsplit(date(), split=" "))
  n1 = c(n1[5],n1[2],n1[3],n1[1])
  now_date = paste(n1, collapse=" ")
  print("現在的日期是:")
  print(now_date)

兩個都分別用function包起來


now_date <- function(){
    print("現在的日期是:")
    print(paste(substr(date(),21,24), 
            substr(date(),5,10), substr(date(),1,3)))
}


now_time <- function(){
    print("現在的時間是:")
    print(substr(date(),12,19))
}

function in function

用一個程式,將上面兩個程式包起來



now <- function(){

  now_date()

  now_time()    

}

now()

## [1] "現在的日期是:"
## [1] "2015 Aug 22 Sat"
## [1] "現在的時間是:"
## [1] "01:40:51"

function儲存

1. 用R studio 或文字編輯器編輯程式,並存成" .r "檔

2. 在R 中用save指令把function,或其他變數、資料集存成" .RData" 檔

把function存起來

用save指令:


save(list = ls(all = now_time), file= "now_time.RData") 
save(list = ls(all = now_date), file= "now_date.RData")
save(list = ls(all = now), file= "now.RData")

存取變數、資料、function

儲存:


save(list = ls(all = TRUE), file= "alldata.RData")

刪除:


rm(list=ls())

讀取:


load("alldata.RData")

小小複習資料結構一下:


numeric1 = c(2, 3, 5) 

string1 = c("aa", "bb", "cc") 

boolean1 = c(TRUE, FALSE, TRUE) 


data1 = data.frame(numeric1, string1, boolean1)

##   number1 string1 boolean1
## 1       2      aa     TRUE
## 2       3      bb    FALSE
## 3       5      cc     TRUE

相似?

看起來 function和資料的樣子是不是很像?

dataf = data.frame(num1, str1, bol1) 


func  = function(str1) { 
        print(paste("Hello World, ", str1)) }

Q & A

課程預告:

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

R 專題實習 , by wush

END…..?

Niklaus Wirth的名言:




程式 =


資料    + function





by 尼克勞斯·維爾特, 1976

Niklaus Wirth的名言:




程式 =


資料 (V) + function





by 尼克勞斯·維爾特, 1976

Niklaus Wirth的名言:




程式 =


資料 (V) + function(V)





by 尼克勞斯·維爾特, 1976

那….我來幹嘛?

泛舟嗎?

來寫一些比較難的 R 的程式吧!~

對了,

如果課程中有任何問題都可以問助教
R社群最神奇的地方就是:







助教什麼都會!

貼心小提醒1:

遇到不會的指令可以用下面方法查詢:

『?』+『指令』

 

『example』『(』+『指令』+『)』

ex:

?list
example(factor)

貼心小提醒2:







善用「tab」按鍵

Syllabus

Syllabus 1:

Flow Control


判斷條件控制 
- if / else

迴圈控制 
- for(),
- while()

Syllabus2:

Debug and Error/Exception Handling


除錯(找蟲)
- debug() / undebug()

程式錯誤及例外處理
- try() / tryCatch()

Flow Control:程式流程控制:

if / else:

==> 如果xxxx,那就xxxx,否則xxxx


Syntex:

    if (condition_1){
        #Do something here....
    } else if (conditon_2){
        #Do something here
    } else {
        #Do something here
    }


Note: **else if** and **else** are optional.

邏輯:




[TRUE] or [T]




[FALSE] or [F]

if /else 邏輯判斷符號

"==":等於

"1" == "1"

[1] TRUE


"1" == "2"

[1] FALSE

if / else 邏輯判斷符號

"<=":小於等於

"1" <= "1"

[1] TRUE


"1" <= "2"

[1] FALSE

if / else 邏輯判斷符號

"<":小於

"1" < "2"

[1] TRUE


"1" < "1"

[1] FALSE

if / else 邏輯判斷符號

">=":大於等於

"1" >= "1"

[1] TRUE


"1" >= "2"

[1] FALSE

if / else 邏輯判斷符號

">":大於

"2" > "1"

[1] TRUE


"1" > "1"

[1] FALSE

if / else 邏輯判斷符號

"!=":不等於

"2" != "1"

[1] TRUE


"1" != "1"

[1] FALSE

if / else 邏輯判斷符號

"&&":邏輯中的「且」 或「and」

("1" == "1") && ("2" == "2")

[1] TRUE


("1" == "2")  &&  ("2" == "2")

[1] FALSE

if / else 邏輯判斷符號

"||":邏輯中的「或」 或「or」

("1" == "1")  ||  ("2" == "2")

[1] TRUE


("1" == "2")  ||  ("2" == "2")

[1] TRUE


("1" == "2")  ||  ("2" == "3")

[1] FALSE

那會了if和邏輯符號,可以怎麼用?

範例:閏年

請判斷輸入的年份是不是閏年?


目前使用的格里曆閏年規則如下:


西元年份除以400可整除=閏年。

西元年份除以4可整除但除以100不可整除=閏年。

西元年份除以4不可整除=平年。

西元年份除以100可整除但除以400不可整除=平年


https://zh.wikipedia.org/zh-tw/%E9%97%B0%E5%B9%B4

step1: 年份除以400可整除=閏年




『如果』 『年份』 『除以』 『400』


『餘數等於』 『0』


『就等於』『閏年』

變成程式的話就是:





如果((年份 對後數取餘數 400) 等於 0){ 

是不是閏年 = 是

}

變成程式的話就是:





if ((year    %%       400)  == 0){ 

is_leap_year = TRUE

}

step2:西元年份除以4可整除,但除以100可整除=不是閏年。


if((year %% 4) == 0){ 

is_leap_year = TRUE }

if((year %% 100) == 0){ 

is_leap_year = FALSE }

咦?好像有地方怪怪的

除以4可整除,那除以100一定也可以整除啊

else()出現了


if ((year1 %% 100)==0){ 
is_leap_year = FALSE
} else if ((year1 %% 4)==0){
is_leap_year = TRUE
} else {
is_leap_year = FALSE
}

step4:西元年份除以100可整除,但除以400不可整除=不是閏年。


if ((year1 %% 100) == 0){ 
is_leap_year = FALSE
} else if ((year1 %% 400) != 0){
is_leap_year = FALSE
}

閏年

還記得前面講過有四個條件嗎?

整理上面的條件


  if ((year1 %% 400)==0){
is_leap_year = TRUE
} else if ((year1 %% 100)==0){
is_leap_year = FALSE
} else if ((year1 %% 4)==0){
is_leap_year = TRUE
} else{
is_leap_year = FALSE
}

用function表示


leap_year=function(year1){
if ((year1 %% 400)==0){ is_leap_year = TRUE } else if ((year1 %% 100)==0){ is_leap_year = FALSE } else if ((year1 %% 4)==0){ is_leap_year = TRUE } else{ is_leap_year = FALSE } return(is_leap_year) }

運用邏輯符號的"!"(not),"&"(and),以及"

"(or)


year1 = 2015  #或是可以用 as.integer(readline("input year:")),來輸入想要的數值
if ( ((!(year1 %% 4)) && 
       (year1 %%100)) || 
       (!(year1 %% 400)) ) {  
  print("Leap year")
} else {  
  print("Not leap year")  
}

迴圈

迴圈說明

某些指令、某些流程重複做多少次,

可減少重複寫code的時間

迴圈使用的時機

1. 重複有限次數

2. 重複次數不能確定

3. 重複無限次數

for() 迴圈


for (累進變數 in 開始條件:停止條件 )


1. 開始條件

2. 累進次數

3. 停止條件

for()

for (累進變數 in 開始條件:終止條件 )


for(x in 1:10) {
  print(x)
}

## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10

for(): ex2

for ( 累進變數 in 向量或集合型態的資料 )


data_in = list(1, 2, 4, -5, "I^love^R", 0, 10)

for(x in data_in) {
  print(x)
}

## [1] 1
## [1] 2
## [1] 4
## [1] -5
## [1] "I^love^R"
## [1] 0
## [1] 10

while()

while (條件不成立的話,就停止)


while(判斷式) {}

如果判斷式不成立就停止,否則一直執行迴圈的程式

最簡單的無限迴圈





while(1){

    print("I love R")   

}

break:


當進入迴圈時,如果想離開迴圈的話,

這時後可以用 break 強制跳出本次的迴圈

再來挑戰無限迴圈:break

加點限制:跑了100次就停止

cnt=0
while(1){
    cnt=cnt+1
    print(paste("I love R, c=",cnt))    
    if(cnt > 5)
        break
}

## [1] "I love R, c= 1"
## [1] "I love R, c= 2"
## [1] "I love R, c= 3"
## [1] "I love R, c= 4"
## [1] "I love R, c= 5"
## [1] "I love R, c= 6"

next: (註)


當進入迴圈時,如果想「暫時忽略」這次迴圈的運算和結果,

這時後可以用 next 忽略本次迴圈,但迴圈仍會執行之後的運算

更正:謝謝學員建議可用next指令,功能類似continue

挑戰無限迴圈2:next


cnt=0
while(1){
  cnt=cnt+1
  if (cnt>5)
    break
  if (cnt==3)
    next
  print(paste("I love R, c=",cnt))  
} 

## [1] 1
## [1] 2
## [1] 4
## [1] 5

會了for,可以怎麼用?

這是copy-paste沒錯

算有多少個閏年

請說明一段時間內,有多少年是閏年



for(年 in 開始年:結束年){ 

判斷是否是閏年

如果是閏年則次數 + 1
}

先輸入條件



yearS = 1000 

# yearS = as.integer(readline("input start year:")) 


yearE = 2015 

# yearE = as.integer(readline("input end year:")) 


year_cnt = 0

用之前講的閏年練習


for (year1 in yearS:yearE){ 

    if ((year1 %% 400)==0){
        is_leap_year = TRUE
    } else if ((year1 %% 100)==0){
        is_leap_year = FALSE
    } else if ((year1 %% 4)==0){
        is_leap_year = TRUE
    } else{
        is_leap_year = FALSE
    }

    if (is_leap_year == TRUE)
    year_cnt = year_cnt + 1 
}
paste("總共有:", year_cnt," 個閏年")

## [1] "總共有: 246  個閏年"

把 leap_year()放到for迴圈中



for (n in yearS:yearE){

  if (leap_year(n) == TRUE){

    year_cnt = year_cnt+1

  }
}
paste("總共有:", year_cnt," 個閏年")

## [1] "總共有: 246  個閏年"

延伸題目:

除了多少年之外,還想知道想知道哪些年是閏年

Debug:除錯

為什麼要除錯:

每天都在問神奇海螺

E=MC^2

人都可能被劈腿,手一定有機會出鎚,

Debug 常用指令:





debug(fun) 

undebug(fun)

使用方法:


debug(now_time)


now_time()


undebug(now_time) 

debug:leap_year()

Error / Exception Handling:錯誤/例外管理

Error/Exception Handling

輸入範例

data_in = list(1, 2, 4, -5, "I^love^R", 0, 10) 
for(input in data_in) {
print(log(input))
}

結果:Error


[1] "0"
[1] "0.693147180559945"
[1] "1.38629436111989"
[1] "NaN"


Error in log(input) : non-numeric argument 

to mathematical function

此外: Warning message:

In log(input) : 產生了 NaNs

Error Handling: 使用try()

try的用法:


data_in = list(1, 2, 4, -5, "I^love^R", 0, 10)

for(input in data_in) {

  try(print(log(input)))
}

## [1] 0
## [1] 0.6931472
## [1] 1.386294
## Warning in log(input): 產生了 NaNs
## [1] NaN
## [1] -Inf
## [1] 2.302585

Error Handling: 使用tryCatch()

可分別處理Warning和Error的事件

先設定發生Error和Warning時的應對方法

func_error = function(e){
print("this is a ERROR!!!")
}

func_warning = function(w){
print("just a wraning")
}

Error Handling: 使用tryCatch()來顯示錯誤


for(input in data_in) {
  tryCatch(print(log(input)),
  warning = func_warning ,
  error = func_error) }
## [1] 0
## [1] 0.6931472
## [1] 1.386294
## [1] "just a wraning"
## [1] "this is a ERROR!!!"
## [1] -Inf
## [1] 2.302585

結果


[1] 0

[1] 0.6931472

[1] 1.386294


[1] "just a wraning"

[1] "this is a ERROR!!!"

[1] -Inf


[1] 2.302585

小天使複習班:

R常用指令1

R常用指令2

小提醒:data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df1 = data.frame(num1, str1, logic1)

# df1表示把data.frame()括號內的資料結合成為data.frame型態
##   num1 str1 logic1
## 1    2   aa   TRUE
## 2    3   bb  FALSE
## 3    5   cc   TRUE

比較c() vs data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df2 = c(num1, str1, logic1)

# df2表示為c()括號中向量資料的結合
## [1] "2"     "3"     "5"     "aa"    "bb"    "cc"    "TRUE"  "FALSE" "TRUE"

比較rbind() vs data.frame()


num1 = c(2, 3, 5) 

str1 = c("aa", "bb", "cc")

logic1 = c(TRUE, FALSE, TRUE)

df3 = rbind(num1, str1, logic1)
# df3表示為rbind()括號中資料的結合
##        [,1]   [,2]    [,3]  
## num1   "2"    "3"     "5"   
## str1   "aa"   "bb"    "cc"  
## logic1 "TRUE" "FALSE" "TRUE"

小提醒:讀取檔案、表格:

讀取R檔並執行

如果想讀取儲存在硬碟的R檔的話,可以用source指令:


source("iris.r")

讀取CSV

CSV:(Comma-separated values:逗號分隔數值)

表格名稱 = read.csv("讀取的檔案")


iris_csv = read.csv("iris.csv") 

View(iris_csv)

一般文字表格

表格名稱 = read.table("讀取的檔案")


iris_tab = read.table("iris.txt")

View(iris_tab)

其他檔案:如excel等

表格名稱 = read.xls("讀取的檔案")

注意:這個需要額外的套件來支援excel格式,請先執行:library(gdata)
注意2:gdata套件的read.xls只能讀excel檔案中第一頁sheet,


library(gdata)

iris_xls = read.xls("iris.xls")

View(iris_xls)

SPSS


library(foreign) 

mydata = read.spss("myfile",

to.data.frame=TRUE)

Stata


library(foreign) 

mydata <- read.dta("mydata.dta")

課程再預告

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

課程預告:

ETL(Extract, Transform and Load ) on R, by Aha

R Visualzation : using ggplot2, by Mansun/Ben/Kyle

R 火力展示 / 閃電秀, by c3h3

R 專題實習 , by wush

Q & A

END!